package com.example.demorabbitmqlisten.rabbitmq;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.rabbitmq.client.Channel;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.messaging.MessageHeaders;
import org.springframework.messaging.handler.annotation.Headers;
import org.springframework.stereotype.Component;

/**
 * 接收消息
 */
@Component
@RequiredArgsConstructor
public class StoreListener {
    private final ApplicationContext context;
    public static final Logger log = LoggerFactory.getLogger(StoreListener.class);
    //    private final IStoreService storeService;
//
//    @RabbitListener(bindings = @QueueBinding(
//            value = @Queue(name = "store.addFavorite.success.queue", durable = "true"), // 队列 起名规则（服务名+业务名+成功+队列），durable持久化
//            exchange = @Exchange(name = "addFavorite.direct"), // 交换机名称，交换机默认类型就行direct，所以不用配置direct
//            key = "addFavorite.success" // 绑定的key
//    ))
//    public void listenAddFavoriteCountsSuccess(Long storeId){
//        storeService.updateStoreFavoriteUsersCountAdd1(storeId);
//    }
    @RabbitListener(queues = "hello")
    public void getHelloLer(String helloMessage) {
        log.info("监听hello队列获取消息:" + helloMessage);
    }

    @RabbitListener(bindings = {
            @QueueBinding(
                    key = "123",
                    value = @Queue(
                            value = "user",
                            durable = "true"
                    ),
                    exchange = @Exchange(
                            value = "user",
                            durable = "true",
                            type = "topic"
                    )
            )
    })
    public void getUser(User user){
        log.info("监听user队列获取消息:{}",user);
    }

    @RabbitListener(bindings = {
            @QueueBinding(
                    key = "${mq.queue.receipt.routingKey}",
//                    key = "*",
                    value = @Queue(
                            value = "${mq.queue.receipt.name}",
                            durable = "${mq.queue.receipt.durable}"
                    ),
                    exchange = @Exchange(
                            value = "${mq.exchange.haocai-chuku-cloud.name}",
                            durable = "${mq.exchange.haocai-chuku-cloud.durable}",
                            type = "${mq.exchange.haocai-chuku-cloud.type}"
                    )
            )
    })
    @RabbitHandler
    public void onReceiveMessage(String msg, Channel channel, @Headers MessageHeaders headers) throws Exception {
        log.info("SpdCloud接收消息, headers=[{}], payload=[{}]", headers, msg);
//        Long deliveryTag = (Long) headers.getOrDefault(AmqpHeaders.DELIVERY_TAG, -1);
        try {
            if (!JSONUtil.isJsonObj(msg)) {
                log.warn("msg非JSON Object格式");
                return;
            }
            MqBaseMessage pojo = JSONUtil.toBean(msg, MqBaseMessage.class);
            MqBaseMessage.MessageHeader messageHeader = pojo.getMessageHeader();

            String type = messageHeader.getOperationType();
            SpdCloudOperationType operationType = SpdCloudOperationType.getByOperationType(type);
            if (operationType == null) {
                log.warn("未找到[{}]类型对应的枚举信息", type);
                return;
            }
            String implementBeanName = operationType.getImplementBeanName();
            log.info("[{}]类型对应的枚举信息, operationType=[{}], name=[{}], implementBeanName=[{}]", type, operationType.getOperationType(), operationType.name(), implementBeanName);
            SpdCloudMqOperationService service = null;
            try {
                service = context.getBean(implementBeanName, SpdCloudMqOperationService.class);
            } catch (BeansException e) {
                log.error("spring容器内获取[" + implementBeanName + "]Bean失败.", e);
            }
            if (service == null) {
                log.warn("spring容器内未找到[{}]Bean", implementBeanName);
                return;
            }

            String payload = pojo.getPayload();
            boolean verify = MqVerifyUtil.verify(payload, pojo.getSign());
            if (!verify) {
                log.warn("MQ消息RSA解密验证失败");
                return;
            }

            log.info("待国密4解密payload=[{}]", payload);
            String decryptPayload = Sm4Util.decrypt(payload);
            log.info("国密4解密后payload=[{}]", decryptPayload);
            boolean result = service.handle(messageHeader, decryptPayload);
            log.info("Service执行结果[{}].", result);
        }catch(Exception e){
            log.error("SpdCloudMQ消息消费失败.", e);
        }finally{
            log.info("SpdCloud接收消息处理结束.");
        }
//        手动确认
//        channel.basicAck(deliveryTag, false);
    }

}
